package com.ywgt.controller;

import com.ywgt.util.HomeCacheManage;
import com.ywgt.pojo.Category;
import com.ywgt.pojo.Goods;
import com.ywgt.service.*;
import com.ywgt.system.SystemConfig;
import com.ywgt.util.ResponseUtil;
import io.swagger.annotations.ApiModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@CrossOrigin
@RestController
@RequestMapping("/wx/home")
@ApiModel("小程序首页")
public class HomeController {

    @Autowired
    private AdService adService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private TopicService topicService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private GrouponRulesService grouponRulesService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private ArticleService articleService;

    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE=new ArrayBlockingQueue<>(9);

    private final static RejectedExecutionHandler HANDLER=new ThreadPoolExecutor.CallerRunsPolicy();

    private static ThreadPoolExecutor executor=new ThreadPoolExecutor(5,10,60, TimeUnit.SECONDS,
            WORK_QUEUE,HANDLER);
    @GetMapping("/index")
    public Object index(@RequestParam(required = false) Integer userId){
        Map<String,Object> data=new HashMap<>();
        Callable<List> couponListCallable=null;
        try {
            if(userId==null){
                couponListCallable=()->couponService.getCoupons(null,null,null,1,3,"add_time","desc");
            }else{
                couponListCallable=()->couponService.queryAvailableList(userId,0,3);
            }
            FutureTask<List> couponListTask = new FutureTask<>(couponListCallable);
            executor.submit(couponListTask);
            if(HomeCacheManage.hasData(HomeCacheManage.INDEX)){
                Map<String, Object> cacheData = HomeCacheManage.getCacheData(HomeCacheManage.INDEX);
                if(cacheData!=null){
                    LocalDateTime expireTime = (LocalDateTime) cacheData.get("expireTime");
                    cacheData.put("couponList",couponListTask.get());
                    return ResponseUtil.ok(cacheData);
                }
            }
            Callable<List> bannerListCallable=()->adService.getIndex();
            Callable<List> articleListCallable=()->articleService.getArticles(null,1,5,"add_time","desc");
            Callable<List> categoryListCallable=()->categoryService.getLevel1();
            Callable<List> newGoodListCallable=()->goodsService.getNewGoods(1, SystemConfig.getNewLimit());
            Callable<List> hotGoodListCallable=()->goodsService.getHotGoods(1,SystemConfig.getHotLimit());
            Callable<List> brandListCallable=()->brandService.getBrands(null,null,1,SystemConfig.getBrandLimit(),"add_time","desc");
            Callable<List> topicListCallable=()->topicService.getTopics(null,null,1,SystemConfig.getTopicLimit(),"add_time","desc");
            Callable<List> grouponListCallable=()->grouponRulesService.getGroupRulesAndGoods(1,5);
            Callable<List> floorGoodsListCallable = this::getCategoryList;
            FutureTask<List> bannerListTask = new FutureTask<>(bannerListCallable);
            FutureTask<List> articleListTask = new FutureTask<>(articleListCallable);
            FutureTask<List> categoryListTask = new FutureTask<>(categoryListCallable);
            FutureTask<List>newGoodListTask = new FutureTask<>(newGoodListCallable);
            FutureTask<List> hotGoodListTask = new FutureTask<>(hotGoodListCallable);
            FutureTask<List> brandListTask = new FutureTask<>(brandListCallable);
            FutureTask<List> topicListTask = new FutureTask<>(topicListCallable);
            FutureTask<List> grouponListTask = new FutureTask<>(grouponListCallable);
            FutureTask<List> floorGoodListTask = new FutureTask<>(floorGoodsListCallable);
            executor.submit(bannerListTask);
            executor.submit(articleListTask);
            executor.submit(categoryListTask);
            executor.submit(newGoodListTask);
            executor.submit(hotGoodListTask);
            executor.submit(topicListTask);
            executor.submit(brandListTask);
            executor.submit(grouponListTask);
            executor.submit(floorGoodListTask);
            data.put("banner", bannerListTask.get());
            data.put("articles", articleListTask.get());
            data.put("channel", categoryListTask.get());
            data.put("couponList", couponListTask.get());
            data.put("newGoodsList", newGoodListTask.get());
            data.put("hotGoodsList", hotGoodListTask.get());
            data.put("brandList", brandListTask.get());
            data.put("topicList", topicListTask.get());
            data.put("grouponList", grouponListTask.get());
            data.put("floorGoodsList", floorGoodListTask.get());
            HomeCacheManage.loadData(HomeCacheManage.INDEX,data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return ResponseUtil.ok(data);
    }

    public List<Map> getCategoryList(){
        List<Map> categoryList = new ArrayList<>();
        List<Category> categories1L = categoryService.getMenu();
        for (Category category : categories1L) {
            List<Category> categories2L = category.getChild();
            List<Goods> goods;
            if(categories2L!=null){
                List<Integer> ids = categories2L.stream().map(Category::getId).collect(Collectors.toList());
                goods=goodsService.getByCategorys(ids,0,SystemConfig.getCatlogListLimit());
            }else {
                goods=new ArrayList<>();
            }
            Map<String, Object> catGoods = new HashMap<>();
            catGoods.put("id", category.getId());
            catGoods.put("name", category.getName());
            catGoods.put("goodsList", goods);
            categoryList.add(catGoods);
        }
        return categoryList;
    }
}
